home *** CD-ROM | disk | FTP | other *** search
/ CD Actual Thematic 7: Programming / CDAT7.iso / Share / Codigo / hh / rsource.exe / Heretic Source / AM_MAP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-13  |  32.1 KB  |  1,353 lines

  1.  
  2. // AM_map.c
  3.  
  4. #include "DoomDef.h"
  5. #include "P_local.h"
  6. #include "AM_map.h"
  7. #include "AM_data.h"
  8. #include <stdio.h>
  9.  
  10. vertex_t KeyPoints[NUMKEYS];
  11.  
  12. #define NUMALIAS 3 // Number of antialiased lines.
  13.  
  14. char *LevelNames[] =
  15. {
  16.     // EPISODE 1 - THE CITY OF THE DAMNED
  17.     "E1M1:  THE DOCKS",
  18.      "E1M2:  THE DUNGEONS",
  19.      "E1M3:  THE GATEHOUSE",
  20.      "E1M4:  THE GUARD TOWER",
  21.      "E1M5:  THE CITADEL",
  22.      "E1M6:  THE CATHEDRAL",
  23.      "E1M7:  THE CRYPTS",
  24.      "E1M8:  HELL'S MAW",
  25.      "E1M9:  THE GRAVEYARD",
  26.     // EPISODE 2 - HELL'S MAW
  27.     "E2M1:  THE CRATER",
  28.      "E2M2:  THE LAVA PITS",
  29.      "E2M3:  THE RIVER OF FIRE",
  30.      "E2M4:  THE ICE GROTTO",
  31.      "E2M5:  THE CATACOMBS",
  32.      "E2M6:  THE LABYRINTH",
  33.      "E2M7:  THE GREAT HALL",
  34.      "E2M8:  THE PORTALS OF CHAOS",
  35.      "E2M9:  THE GLACIER",
  36.     // EPISODE 3 - THE DOME OF D'SPARIL
  37.      "E3M1:  THE STOREHOUSE",
  38.      "E3M2:  THE CESSPOOL",
  39.      "E3M3:  THE CONFLUENCE",
  40.      "E3M4:  THE AZURE FORTRESS",
  41.      "E3M5:  THE OPHIDIAN LAIR",
  42.      "E3M6:  THE HALLS OF FEAR",
  43.      "E3M7:  THE CHASM",
  44.      "E3M8:  D'SPARIL'S KEEP",
  45.      "E3M9:  THE AQUIFER",
  46.     // EPISODE 4: THE OSSUARY
  47.     "E4M1:  CATAFALQUE",
  48.     "E4M2:  BLOCKHOUSE",
  49.     "E4M3:  AMBULATORY",
  50.     "E4M4:  SEPULCHER",
  51.     "E4M5:  GREAT STAIR",
  52.     "E4M6:  HALLS OF THE APOSTATE",
  53.     "E4M7:  RAMPARTS OF PERDITION",
  54.     "E4M8:  SHATTERED BRIDGE",
  55.     "E4M9:  MAUSOLEUM",
  56.     // EPISODE 5: THE STAGNANT DEMESNE
  57.     "E5M1:  OCHRE CLIFFS",
  58.     "E5M2:  RAPIDS",
  59.     "E5M3:  QUAY",
  60.     "E5M4:  COURTYARD",
  61.     "E5M5:  HYDRATYR",
  62.     "E5M6:  COLONNADE",
  63.     "E5M7:  FOETID MANSE",
  64.     "E5M8:  FIELD OF JUDGEMENT",
  65.     "E5M9:  SKEIN OF D'SPARIL"
  66. };
  67.  
  68. static int cheating = 0;
  69. static int grid = 0;
  70.  
  71. static int leveljuststarted = 1; // kluge until AM_LevelInit() is called
  72.  
  73. boolean    automapactive = false;
  74. static int finit_width = SCREENWIDTH;
  75. static int finit_height = SCREENHEIGHT-42;
  76. static int f_x, f_y; // location of window on screen
  77. static int f_w, f_h; // size of window on screen
  78. static int lightlev; // used for funky strobing effect
  79. static byte *fb; // pseudo-frame buffer
  80. static int amclock;
  81.  
  82. static mpoint_t m_paninc; // how far the window pans each tic (map coords)
  83. static fixed_t mtof_zoommul; // how far the window zooms in each tic (map coords)
  84. static fixed_t ftom_zoommul; // how far the window zooms in each tic (fb coords)
  85.  
  86. static fixed_t m_x, m_y;   // LL x,y where the window is on the map (map coords)
  87. static fixed_t m_x2, m_y2; // UR x,y where the window is on the map (map coords)
  88.  
  89. // width/height of window on map (map coords)
  90. static fixed_t m_w, m_h;
  91. static fixed_t min_x, min_y; // based on level size
  92. static fixed_t max_x, max_y; // based on level size
  93. static fixed_t max_w, max_h; // max_x-min_x, max_y-min_y
  94. static fixed_t min_w, min_h; // based on player size
  95. static fixed_t min_scale_mtof; // used to tell when to stop zooming out
  96. static fixed_t max_scale_mtof; // used to tell when to stop zooming in
  97.  
  98. // old stuff for recovery later
  99. static fixed_t old_m_w, old_m_h;
  100. static fixed_t old_m_x, old_m_y;
  101.  
  102. // old location used by the Follower routine
  103. static mpoint_t f_oldloc;
  104.  
  105. // used by MTOF to scale from map-to-frame-buffer coords
  106. static fixed_t scale_mtof = INITSCALEMTOF;
  107. // used by FTOM to scale from frame-buffer-to-map coords (=1/scale_mtof)
  108. static fixed_t scale_ftom;
  109.  
  110. static player_t *plr; // the player represented by an arrow
  111. static vertex_t oldplr;
  112.  
  113. //static patch_t *marknums[10]; // numbers used for marking by the automap
  114. //static mpoint_t markpoints[AM_NUMMARKPOINTS]; // where the points are
  115. //static int markpointnum = 0; // next point to be assigned
  116.  
  117. static int followplayer = 1; // specifies whether to follow the player around
  118.  
  119. static char cheat_amap[] = { 'r','a','v','m','a','p' };
  120.  
  121. static byte cheatcount=0;
  122.  
  123. extern boolean viewactive;
  124.  
  125. static byte antialias[NUMALIAS][8]=
  126. {
  127.     {96, 97, 98, 99, 100, 101, 102, 103},
  128.     {110, 109, 108, 107, 106, 105, 104, 103},
  129.     {75, 76, 77, 78, 79, 80, 81, 103}
  130. };
  131. /*
  132. static byte *aliasmax[NUMALIAS] = {
  133.     &antialias[0][7], &antialias[1][7], &antialias[2][7]
  134. };*/
  135.  
  136. static byte *maplump; // pointer to the raw data for the automap background.
  137. static short mapystart=0; // y-value for the start of the map bitmap...used in the paralax stuff.
  138. static short mapxstart=0; //x-value for the bitmap.
  139.  
  140. //byte screens[][SCREENWIDTH*SCREENHEIGHT];
  141. //void V_MarkRect (int x, int y, int width, int height);
  142.  
  143. // Functions
  144.  
  145. void DrawWuLine(int X0, int Y0, int X1, int Y1, byte *BaseColor,
  146.     int NumLevels, unsigned short IntensityBits);
  147.  
  148. // Calculates the slope and slope according to the x-axis of a line
  149. // segment in map coordinates (with the upright y-axis n' all) so
  150. // that it can be used with the brain-dead drawing stuff.
  151.  
  152. // Ripped out for Heretic
  153. /*
  154. void AM_getIslope(mline_t *ml, islope_t *is)
  155. {
  156.   int dx, dy;
  157.  
  158.   dy = ml->a.y - ml->b.y;
  159.   dx = ml->b.x - ml->a.x;
  160.   if (!dy) is->islp = (dx<0?-MAXINT:MAXINT);
  161.   else is->islp = FixedDiv(dx, dy);
  162.   if (!dx) is->slp = (dy<0?-MAXINT:MAXINT);
  163.   else is->slp = FixedDiv(dy, dx);
  164. }
  165. */
  166.  
  167. void AM_activateNewScale(void)
  168. {
  169.   m_x += m_w/2;
  170.   m_y += m_h/2;
  171.   m_w = FTOM(f_w);
  172.   m_h = FTOM(f_h);
  173.   m_x -= m_w/2;
  174.   m_y -= m_h/2;
  175.   m_x2 = m_x + m_w;
  176.   m_y2 = m_y + m_h;
  177. }
  178.  
  179. void AM_saveScaleAndLoc(void)
  180. {
  181.   old_m_x = m_x;
  182.   old_m_y = m_y;
  183.   old_m_w = m_w;
  184.   old_m_h = m_h;
  185. }
  186.  
  187. void AM_restoreScaleAndLoc(void)
  188. {
  189.  
  190.   m_w = old_m_w;
  191.   m_h = old_m_h;
  192.   if (!followplayer)
  193.   {
  194.     m_x = old_m_x;
  195.     m_y = old_m_y;
  196.   } else {
  197.     m_x = plr->mo->x - m_w/2;
  198.     m_y = plr->mo->y - m_h/2;
  199.   }
  200.   m_x2 = m_x + m_w;
  201.   m_y2 = m_y + m_h;
  202.  
  203.   // Change the scaling multipliers
  204.   scale_mtof = FixedDiv(f_w<<FRACBITS, m_w);
  205.   scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
  206. }
  207.  
  208. // adds a marker at the current location
  209.  
  210. /*
  211. void AM_addMark(void)
  212. {
  213.   markpoints[markpointnum].x = m_x + m_w/2;
  214.   markpoints[markpointnum].y = m_y + m_h/2;
  215.   markpointnum = (markpointnum + 1) % AM_NUMMARKPOINTS;
  216.  
  217. }
  218. */
  219. void AM_findMinMaxBoundaries(void)
  220. {
  221.   int i;
  222.   fixed_t a, b;
  223.  
  224.   min_x = min_y = MAXINT;
  225.   max_x = max_y = -MAXINT;
  226.   for (i=0;i<numvertexes;i++)
  227.   {
  228.     if (vertexes[i].x < min_x) min_x = vertexes[i].x;
  229.     else if (vertexes[i].x > max_x) max_x = vertexes[i].x;
  230.     if (vertexes[i].y < min_y) min_y = vertexes[i].y;
  231.     else if (vertexes[i].y > max_y) max_y = vertexes[i].y;
  232.   }
  233.   max_w = max_x - min_x;
  234.   max_h = max_y - min_y;
  235.   min_w = 2*PLAYERRADIUS;
  236.   min_h = 2*PLAYERRADIUS;
  237.  
  238.   a = FixedDiv(f_w<<FRACBITS, max_w);
  239.   b = FixedDiv(f_h<<FRACBITS, max_h);
  240.   min_scale_mtof = a < b ? a : b;
  241.  
  242.   max_scale_mtof = FixedDiv(f_h<<FRACBITS, 2*PLAYERRADIUS);
  243.  
  244. }
  245.  
  246. void AM_changeWindowLoc(void)
  247. {
  248.   if (m_paninc.x || m_paninc.y)
  249.   {
  250.     followplayer = 0;
  251.     f_oldloc.x = MAXINT;
  252.   }
  253.  
  254.   m_x += m_paninc.x;
  255.   m_y += m_paninc.y;
  256.  
  257.   if (m_x + m_w/2 > max_x)
  258.   {
  259.           m_x = max_x - m_w/2;
  260.         m_paninc.x=0;
  261.   }
  262.   else if (m_x + m_w/2 < min_x)
  263.   {
  264.           m_x = min_x - m_w/2;
  265.         m_paninc.x=0;
  266.   }
  267.   if (m_y + m_h/2 > max_y)
  268.   {
  269.           m_y = max_y - m_h/2;
  270.         m_paninc.y=0;
  271.   }
  272.   else if (m_y + m_h/2 < min_y)
  273.   {
  274.           m_y = min_y - m_h/2;
  275.         m_paninc.y=0;
  276.   }
  277. /*
  278.   mapxstart += MTOF(m_paninc.x+FRACUNIT/2);
  279.   mapystart -= MTOF(m_paninc.y+FRACUNIT/2);
  280.   if(mapxstart >= finit_width)
  281.         mapxstart -= finit_width;
  282.   if(mapxstart < 0)
  283.         mapxstart += finit_width;
  284.   if(mapystart >= finit_height)
  285.         mapystart -= finit_height;
  286.   if(mapystart < 0)
  287.         mapystart += finit_height;
  288. */
  289.   m_x2 = m_x + m_w;
  290.   m_y2 = m_y + m_h;
  291. }
  292.  
  293. void AM_initVariables(void)
  294. {
  295.   int pnum;
  296.     thinker_t *think;
  297.     mobj_t *mo;
  298.  
  299.   //static event_t st_notify = { ev_keyup, AM_MSGENTERED };
  300.  
  301.   automapactive = true;
  302.   fb = screen;
  303.  
  304.   f_oldloc.x = MAXINT;
  305.   amclock = 0;
  306.   lightlev = 0;
  307.  
  308.   m_paninc.x = m_paninc.y = 0;
  309.   ftom_zoommul = FRACUNIT;
  310.   mtof_zoommul = FRACUNIT;
  311.  
  312.   m_w = FTOM(f_w);
  313.   m_h = FTOM(f_h);
  314.  
  315.   // find player to center on initially
  316.   if (!playeringame[pnum = consoleplayer])
  317.     for (pnum=0;pnum<MAXPLAYERS;pnum++) if (playeringame[pnum]) break;
  318.   plr = &players[pnum];
  319.   oldplr.x = plr->mo->x;
  320.   oldplr.y = plr->mo->y;
  321.   m_x = plr->mo->x - m_w/2;
  322.   m_y = plr->mo->y - m_h/2;
  323.   AM_changeWindowLoc();
  324.  
  325.   // for saving & restoring
  326.   old_m_x = m_x;
  327.   old_m_y = m_y;
  328.   old_m_w = m_w;
  329.   old_m_h = m_h;
  330.  
  331.     // load in the location of keys, if in baby mode
  332.  
  333.     memset(KeyPoints, 0, sizeof(vertex_t)*3);
  334.     if(gameskill == sk_baby)
  335.     {
  336.         for(think = thinkercap.next; think != &thinkercap; think = think->next)
  337.         {
  338.             if(think->function != P_MobjThinker)
  339.             { //not a mobj
  340.                 continue;
  341.             }
  342.             mo = (mobj_t *)think;
  343.             if(mo->type == MT_CKEY)
  344.             {
  345.                 KeyPoints[0].x = mo->x;
  346.                 KeyPoints[0].y = mo->y;
  347.             }
  348.             else if(mo->type == MT_AKYY)
  349.             {
  350.                 KeyPoints[1].x = mo->x;
  351.                 KeyPoints[1].y = mo->y;
  352.             }
  353.             else if(mo->type == MT_BKYY)
  354.             {
  355.                 KeyPoints[2].x = mo->x;
  356.                 KeyPoints[2].y = mo->y;
  357.             }
  358.         }
  359.     }
  360.  
  361.   // inform the status bar of the change
  362. //c  ST_Responder(&st_notify);
  363. }
  364.  
  365. void AM_loadPics(void)
  366. {
  367.   //int i;
  368.   //char namebuf[9];
  369. /*  for (i=0;i<10;i++)
  370.   {
  371.     sprintf(namebuf, "AMMNUM%d", i);
  372.     marknums[i] = W_CacheLumpName(namebuf, PU_STATIC);
  373.   }*/
  374.   maplump = W_CacheLumpName("AUTOPAGE", PU_STATIC);
  375. }
  376.  
  377. /*void AM_unloadPics(void)
  378. {
  379.   int i;
  380.   for (i=0;i<10;i++) Z_ChangeTag(marknums[i], PU_CACHE);
  381.  
  382. }*/
  383.  
  384. /*
  385. void AM_clearMarks(void)
  386. {
  387.   int i;
  388.   for (i=0;i<AM_NUMMARKPOINTS;i++) markpoints[i].x = -1; // means empty
  389.   markpointnum = 0;
  390. }
  391. */
  392.  
  393. // should be called at the start of every level
  394. // right now, i figure it out myself
  395.  
  396. void AM_LevelInit(void)
  397. {
  398.   leveljuststarted = 0;
  399.  
  400.   f_x = f_y = 0;
  401.   f_w = finit_width;
  402.   f_h = finit_height;
  403.     mapxstart = mapystart = 0;
  404.  
  405.  
  406. //  AM_clearMarks();
  407.  
  408.   AM_findMinMaxBoundaries();
  409.   scale_mtof = FixedDiv(min_scale_mtof, (int) (0.7*FRACUNIT));
  410.   if (scale_mtof > max_scale_mtof) scale_mtof = min_scale_mtof;
  411.   scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
  412. }
  413.  
  414. static boolean stopped = true;
  415.  
  416. void AM_Stop (void)
  417. {
  418.   //static event_t st_notify = { 0, ev_keyup, AM_MSGEXITED };
  419.  
  420. //  AM_unloadPics();
  421.   automapactive = false;
  422. //  ST_Responder(&st_notify);
  423.   stopped = true;
  424.     BorderNeedRefresh = true;
  425. }
  426.  
  427. void AM_Start (void)
  428. {
  429.   static int lastlevel = -1, lastepisode = -1;
  430.  
  431.   if (!stopped) AM_Stop();
  432.   stopped = false;
  433.   if(gamestate != GS_LEVEL)
  434.   {
  435.         return; // don't show automap if we aren't in a game!
  436.   }
  437.   if (lastlevel != gamemap || lastepisode != gameepisode)
  438.   {
  439.     AM_LevelInit();
  440.     lastlevel = gamemap;
  441.     lastepisode = gameepisode;
  442.   }
  443.   AM_initVariables();
  444.   AM_loadPics();
  445. }
  446.  
  447. // set the window scale to the maximum size
  448.  
  449. void AM_minOutWindowScale(void)
  450. {
  451.   scale_mtof = min_scale_mtof;
  452.   scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
  453.   AM_activateNewScale();
  454. }
  455.  
  456. // set the window scale to the minimum size
  457.  
  458. void AM_maxOutWindowScale(void)
  459. {
  460.   scale_mtof = max_scale_mtof;
  461.   scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
  462.   AM_activateNewScale();
  463. }
  464.  
  465. boolean AM_Responder (event_t *ev)
  466. {
  467.   int rc;
  468.   static int cheatstate=0;
  469.   static int bigstate=0;
  470.  
  471.   rc = false;
  472.   if (!automapactive)
  473.   {
  474.     if (ev->type == ev_keydown && ev->data1 == AM_STARTKEY
  475.         && gamestate == GS_LEVEL)
  476.     {
  477.       AM_Start ();
  478.         viewactive = false;
  479. //      viewactive = true;
  480.       rc = true;
  481.     }
  482.   }
  483.   else if (ev->type == ev_keydown)
  484.   {
  485.  
  486.     rc = true;
  487.     switch(ev->data1)
  488.     {
  489.       case AM_PANRIGHTKEY: // pan right
  490.     if (!followplayer) m_paninc.x = FTOM(F_PANINC);
  491.     else rc = false;
  492.     break;
  493.       case AM_PANLEFTKEY: // pan left
  494.     if (!followplayer) m_paninc.x = -FTOM(F_PANINC);
  495.     else rc = false;
  496.     break;
  497.       case AM_PANUPKEY: // pan up
  498.     if (!followplayer) m_paninc.y = FTOM(F_PANINC);
  499.     else rc = false;
  500.     break;
  501.       case AM_PANDOWNKEY: // pan down
  502.     if (!followplayer) m_paninc.y = -FTOM(F_PANINC);
  503.     else rc = false;
  504.     break;
  505.       case AM_ZOOMOUTKEY: // zoom out
  506.     mtof_zoommul = M_ZOOMOUT;
  507.     ftom_zoommul = M_ZOOMIN;
  508.     break;
  509.       case AM_ZOOMINKEY: // zoom in
  510.     mtof_zoommul = M_ZOOMIN;
  511.     ftom_zoommul = M_ZOOMOUT;
  512.     break;
  513.       case AM_ENDKEY:
  514.     bigstate = 0;
  515.     viewactive = true;
  516.     AM_Stop ();
  517.     break;
  518.       case AM_GOBIGKEY:
  519.     bigstate = !bigstate;
  520.     if (bigstate)
  521.     {
  522.       AM_saveScaleAndLoc();
  523.       AM_minOutWindowScale();
  524.     }
  525.     else AM_restoreScaleAndLoc();
  526.     break;
  527.       case AM_FOLLOWKEY:
  528.     followplayer = !followplayer;
  529.     f_oldloc.x = MAXINT;
  530.     P_SetMessage(plr, followplayer ? AMSTR_FOLLOWON : AMSTR_FOLLOWOFF, true);
  531.     break;
  532. /*
  533.       case AM_GRIDKEY:
  534.     grid = !grid;
  535.     plr->message = grid ? AMSTR_GRIDON : AMSTR_GRIDOFF;
  536.     break;
  537.       case AM_MARKKEY:
  538.     sprintf(buffer, "%s %d", AMSTR_MARKEDSPOT, markpointnum);
  539.     plr->message = buffer;
  540.       AM_addMark();
  541.       break;
  542.       case AM_CLEARMARKKEY:
  543.       AM_clearMarks();
  544.     plr->message = AMSTR_MARKSCLEARED;
  545.       break;
  546. */
  547.       default:
  548.     cheatstate=0;
  549.     rc = false;
  550.     }
  551.    if(cheat_amap[cheatcount]==ev->data1 && !netgame)
  552.         cheatcount++;
  553.     else
  554.         cheatcount=0;
  555.     if(cheatcount==6)
  556.    {
  557.         cheatcount=0;
  558.         rc = false;
  559.       cheating = (cheating+1) % 3;
  560.     }
  561.   }
  562.  
  563.   else if (ev->type == ev_keyup)
  564.   {
  565.     rc = false;
  566.     switch (ev->data1)
  567.     {
  568.       case AM_PANRIGHTKEY:
  569.     if (!followplayer) m_paninc.x = 0;
  570.     break;
  571.       case AM_PANLEFTKEY:
  572.     if (!followplayer) m_paninc.x = 0;
  573.     break;
  574.       case AM_PANUPKEY:
  575.     if (!followplayer) m_paninc.y = 0;
  576.     break;
  577.       case AM_PANDOWNKEY:
  578.     if (!followplayer) m_paninc.y = 0;
  579.     break;
  580.       case AM_ZOOMOUTKEY:
  581.       case AM_ZOOMINKEY:
  582.     mtof_zoommul = FRACUNIT;
  583.     ftom_zoommul = FRACUNIT;
  584.     break;
  585.     }
  586.   }
  587.  
  588.   return rc;
  589.  
  590. }
  591.  
  592. void AM_changeWindowScale(void)
  593. {
  594.  
  595.   // Change the scaling multipliers
  596.   scale_mtof = FixedMul(scale_mtof, mtof_zoommul);
  597.   scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
  598.  
  599.   if (scale_mtof < min_scale_mtof) AM_minOutWindowScale();
  600.   else if (scale_mtof > max_scale_mtof) AM_maxOutWindowScale();
  601.   else AM_activateNewScale();
  602. }
  603.  
  604. void AM_doFollowPlayer(void)
  605. {
  606.   if (f_oldloc.x != plr->mo->x || f_oldloc.y != plr->mo->y)
  607.   {
  608. //  m_x = FTOM(MTOF(plr->mo->x - m_w/2));
  609. //  m_y = FTOM(MTOF(plr->mo->y - m_h/2));
  610. //  m_x = plr->mo->x - m_w/2;
  611. //  m_y = plr->mo->y - m_h/2;
  612.     m_x = FTOM(MTOF(plr->mo->x)) - m_w/2;
  613.     m_y = FTOM(MTOF(plr->mo->y)) - m_h/2;
  614.     m_x2 = m_x + m_w;
  615.     m_y2 = m_y + m_h;
  616.  
  617.        // do the parallax parchment scrolling.
  618. /*
  619.      dmapx = (MTOF(plr->mo->x)-MTOF(f_oldloc.x)); //fixed point
  620.      dmapy = (MTOF(f_oldloc.y)-MTOF(plr->mo->y));
  621.  
  622.      if(f_oldloc.x == MAXINT) //to eliminate an error when the user first
  623.         dmapx=0;  //goes into the automap.
  624.      mapxstart += dmapx;
  625.      mapystart += dmapy;
  626.  
  627.        while(mapxstart >= finit_width)
  628.             mapxstart -= finit_width;
  629.     while(mapxstart < 0)
  630.             mapxstart += finit_width;
  631.     while(mapystart >= finit_height)
  632.             mapystart -= finit_height;
  633.     while(mapystart < 0)
  634.             mapystart += finit_height;
  635. */
  636.      f_oldloc.x = plr->mo->x;
  637.     f_oldloc.y = plr->mo->y;
  638.   }
  639. }
  640.  
  641. // Ripped out for Heretic
  642. /*
  643. void AM_updateLightLev(void)
  644. {
  645.   static nexttic = 0;
  646. //static int litelevels[] = { 0, 3, 5, 6, 6, 7, 7, 7 };
  647.   static int litelevels[] = { 0, 4, 7, 10, 12, 14, 15, 15 };
  648.   static int litelevelscnt = 0;
  649.  
  650.   // Change light level
  651.   if (amclock>nexttic)
  652.   {
  653.     lightlev = litelevels[litelevelscnt++];
  654.     if (litelevelscnt == sizeof(litelevels)/sizeof(int)) litelevelscnt = 0;
  655.     nexttic = amclock + 6 - (amclock % 6);
  656.   }
  657. }
  658. */
  659.  
  660. void AM_Ticker (void)
  661. {
  662.  
  663.   if (!automapactive) return;
  664.  
  665.   amclock++;
  666.  
  667.   if (followplayer) AM_doFollowPlayer();
  668.  
  669.   // Change the zoom if necessary
  670.   if (ftom_zoommul != FRACUNIT) AM_changeWindowScale();
  671.  
  672.   // Change x,y location
  673.   if (m_paninc.x || m_paninc.y) AM_changeWindowLoc();
  674.   // Update light level
  675. // AM_updateLightLev();
  676.  
  677. }
  678.  
  679. void AM_clearFB(int color)
  680. {
  681.     int i, j;
  682.     int dmapx;
  683.     int dmapy;
  684.  
  685.     if(followplayer)
  686.     {
  687.         dmapx = (MTOF(plr->mo->x)-MTOF(oldplr.x)); //fixed point
  688.         dmapy = (MTOF(oldplr.y)-MTOF(plr->mo->y));
  689.  
  690.         oldplr.x = plr->mo->x;
  691.         oldplr.y = plr->mo->y;
  692. //        if(f_oldloc.x == MAXINT) //to eliminate an error when the user first
  693. //            dmapx=0;  //goes into the automap.
  694.         mapxstart += dmapx>>1;
  695.         mapystart += dmapy>>1;
  696.  
  697.           while(mapxstart >= finit_width)
  698.             mapxstart -= finit_width;
  699.        while(mapxstart < 0)
  700.             mapxstart += finit_width;
  701.        while(mapystart >= finit_height)
  702.             mapystart -= finit_height;
  703.        while(mapystart < 0)
  704.             mapystart += finit_height;
  705.     }
  706.     else
  707.     {
  708.         mapxstart += (MTOF(m_paninc.x)>>1);
  709.         mapystart -= (MTOF(m_paninc.y)>>1);
  710.         if(mapxstart >= finit_width)
  711.             mapxstart -= finit_width;
  712.         if(mapxstart < 0)
  713.             mapxstart += finit_width;
  714.         if(mapystart >= finit_height)
  715.         mapystart -= finit_height;
  716.         if(mapystart < 0)
  717.         mapystart += finit_height;
  718.     }
  719.  
  720.     //blit the automap background to the screen.
  721.     j=mapystart*finit_width;
  722.     for(i=0;i<finit_height;i++)
  723.     {
  724.         memcpy(screen+i*finit_width, maplump+j+mapxstart, finit_width-mapxstart);
  725.         memcpy(screen+i*finit_width+finit_width-mapxstart, maplump+j, mapxstart);
  726.         j += finit_width;
  727.         if(j >= finit_height*finit_width)
  728.             j=0;
  729.     }
  730.  
  731. //     memcpy(screen, maplump, finit_width*finit_height);
  732. //  memset(fb, color, f_w*f_h);
  733. }
  734.  
  735. // Based on Cohen-Sutherland clipping algorithm but with a slightly
  736. // faster reject and precalculated slopes.  If I need the speed, will
  737. // hash algorithm to the common cases.
  738.  
  739. boolean AM_clipMline(mline_t *ml, fline_t *fl)
  740. {
  741.   enum { LEFT=1, RIGHT=2, BOTTOM=4, TOP=8 };
  742.   register outcode1 = 0, outcode2 = 0, outside;
  743.   fpoint_t tmp;
  744.   int dx, dy;
  745.  
  746. #define DOOUTCODE(oc, mx, my) \
  747.   (oc) = 0; \
  748.   if ((my) < 0) (oc) |= TOP; \
  749.   else if ((my) >= f_h) (oc) |= BOTTOM; \
  750.   if ((mx) < 0) (oc) |= LEFT; \
  751.   else if ((mx) >= f_w) (oc) |= RIGHT
  752.  
  753.   // do trivial rejects and outcodes
  754.   if (ml->a.y > m_y2) outcode1 = TOP;
  755.   else if (ml->a.y < m_y) outcode1 = BOTTOM;
  756.   if (ml->b.y > m_y2) outcode2 = TOP;
  757.   else if (ml->b.y < m_y) outcode2 = BOTTOM;
  758.   if (outcode1 & outcode2) return false; // trivially outside
  759.  
  760.   if (ml->a.x < m_x) outcode1 |= LEFT;
  761.   else if (ml->a.x > m_x2) outcode1 |= RIGHT;
  762.   if (ml->b.x < m_x) outcode2 |= LEFT;
  763.   else if (ml->b.x > m_x2) outcode2 |= RIGHT;
  764.   if (outcode1 & outcode2) return false; // trivially outside
  765.  
  766.   // transform to frame-buffer coordinates.
  767.   fl->a.x = CXMTOF(ml->a.x);
  768.   fl->a.y = CYMTOF(ml->a.y);
  769.   fl->b.x = CXMTOF(ml->b.x);
  770.   fl->b.y = CYMTOF(ml->b.y);
  771.   DOOUTCODE(outcode1, fl->a.x, fl->a.y);
  772.   DOOUTCODE(outcode2, fl->b.x, fl->b.y);
  773.   if (outcode1 & outcode2) return false;
  774.  
  775.   while (outcode1 | outcode2)
  776.   {
  777.     // may be partially inside box
  778.     // find an outside point
  779.     if (outcode1) outside = outcode1;
  780.     else outside = outcode2;
  781.     // clip to each side
  782.     if (outside & TOP)
  783.     {
  784.       dy = fl->a.y - fl->b.y;
  785.       dx = fl->b.x - fl->a.x;
  786.       tmp.x = fl->a.x + (dx*(fl->a.y))/dy;
  787.       tmp.y = 0;
  788.     }
  789.     else if (outside & BOTTOM)
  790.     {
  791.       dy = fl->a.y - fl->b.y;
  792.       dx = fl->b.x - fl->a.x;
  793.       tmp.x = fl->a.x + (dx*(fl->a.y-f_h))/dy;
  794.       tmp.y = f_h-1;
  795.     }
  796.     else if (outside & RIGHT)
  797.     {
  798.       dy = fl->b.y - fl->a.y;
  799.       dx = fl->b.x - fl->a.x;
  800.       tmp.y = fl->a.y + (dy*(f_w-1 - fl->a.x))/dx;
  801.       tmp.x = f_w-1;
  802.     }
  803.     else if (outside & LEFT)
  804.     {
  805.       dy = fl->b.y - fl->a.y;
  806.       dx = fl->b.x - fl->a.x;
  807.       tmp.y = fl->a.y + (dy*(-fl->a.x))/dx;
  808.       tmp.x = 0;
  809.     }
  810.     if (outside == outcode1)
  811.     {
  812.       fl->a = tmp;
  813.       DOOUTCODE(outcode1, fl->a.x, fl->a.y);
  814.     } else {
  815.       fl->b = tmp;
  816.       DOOUTCODE(outcode2, fl->b.x, fl->b.y);
  817.     }
  818.     if (outcode1 & outcode2) return false; // trivially outside
  819.   }
  820.  
  821.   return true;
  822. }
  823. #undef DOOUTCODE
  824.  
  825. // Classic Bresenham w/ whatever optimizations I need for speed
  826.  
  827. void AM_drawFline(fline_t *fl, int color)
  828. {
  829.  
  830.   register int x, y, dx, dy, sx, sy, ax, ay, d;
  831.   static fuck = 0;
  832.  
  833.   switch(color)
  834.   {
  835.         case WALLCOLORS:
  836.               DrawWuLine(fl->a.x, fl->a.y, fl->b.x, fl->b.y, &antialias[0][0], 8, 3);
  837.             break;
  838.         case FDWALLCOLORS:
  839.               DrawWuLine(fl->a.x, fl->a.y, fl->b.x, fl->b.y, &antialias[1][0], 8, 3);
  840.             break;
  841.         case CDWALLCOLORS:
  842.               DrawWuLine(fl->a.x, fl->a.y, fl->b.x, fl->b.y, &antialias[2][0], 8, 3);
  843.             break;
  844.         default:
  845.           {
  846.                       // For debugging only
  847.                   if (   fl->a.x < 0 || fl->a.x >= f_w
  848.                       || fl->a.y < 0 || fl->a.y >= f_h
  849.                       || fl->b.x < 0 || fl->b.x >= f_w
  850.                       || fl->b.y < 0 || fl->b.y >= f_h)
  851.                   {
  852.                     fprintf(stderr, "fuck %d \r", fuck++);
  853.                     return;
  854.                   }
  855.  
  856.                   #define DOT(xx,yy,cc) fb[(yy)*f_w+(xx)]=(cc) //the MACRO!
  857.  
  858.                   dx = fl->b.x - fl->a.x;
  859.                   ax = 2 * (dx<0 ? -dx : dx);
  860.                   sx = dx<0 ? -1 : 1;
  861.  
  862.                   dy = fl->b.y - fl->a.y;
  863.                   ay = 2 * (dy<0 ? -dy : dy);
  864.                   sy = dy<0 ? -1 : 1;
  865.  
  866.                   x = fl->a.x;
  867.                   y = fl->a.y;
  868.  
  869.                   if (ax > ay)
  870.                   {
  871.                     d = ay - ax/2;
  872.                     while (1)
  873.                     {
  874.                       DOT(x,y,color);
  875.                       if (x == fl->b.x) return;
  876.                       if (d>=0)
  877.                       {
  878.                     y += sy;
  879.                     d -= ax;
  880.                       }
  881.                       x += sx;
  882.                       d += ay;
  883.                     }
  884.                   } else {
  885.                     d = ax - ay/2;
  886.                     while (1)
  887.                     {
  888.                       DOT(x, y, color);
  889.                       if (y == fl->b.y) return;
  890.                       if (d >= 0)
  891.                       {
  892.                     x += sx;
  893.                     d -= ay;
  894.                       }
  895.                       y += sy;
  896.                       d += ax;
  897.                     }
  898.                   }
  899.           }
  900.   }
  901. }
  902.  
  903. /* Wu antialiased line drawer.
  904.  * (X0,Y0),(X1,Y1) = line to draw
  905.  * BaseColor = color # of first color in block used for antialiasing, the
  906.  *          100% intensity version of the drawing color
  907.  * NumLevels = size of color block, with BaseColor+NumLevels-1 being the
  908.  *          0% intensity version of the drawing color
  909.  * IntensityBits = log base 2 of NumLevels; the # of bits used to describe
  910.  *          the intensity of the drawing color. 2**IntensityBits==NumLevels
  911.  */
  912. void PUTDOT(short xx,short yy,byte *cc, byte *cm)
  913. {
  914.     static int oldyy;
  915.     static int oldyyshifted;
  916.     byte *oldcc=cc;
  917.  
  918.     if(xx < 32)
  919.         cc += 7-(xx>>2);
  920.     else if(xx > (finit_width - 32))
  921.         cc += 7-((finit_width-xx) >> 2);
  922. //    if(cc==oldcc) //make sure that we don't double fade the corners.
  923. //    {
  924.         if(yy < 32)
  925.             cc += 7-(yy>>2);
  926.         else if(yy > (finit_height - 32))
  927.             cc += 7-((finit_height-yy) >> 2);
  928. //    }
  929.     if(cc > cm && cm != NULL)
  930.     {
  931.         cc = cm;
  932.     }
  933.     else if(cc > oldcc+6) // don't let the color escape from the fade table...
  934.     {
  935.         cc=oldcc+6;
  936.     }
  937.     if(yy == oldyy+1)
  938.     {
  939.         oldyy++;
  940.         oldyyshifted += 320;
  941.     }
  942.     else if(yy == oldyy-1)
  943.     {
  944.         oldyy--;
  945.         oldyyshifted -= 320;
  946.     }
  947.     else if(yy != oldyy)
  948.     {
  949.         oldyy = yy;
  950.         oldyyshifted = yy*320;
  951.     }
  952.     fb[oldyyshifted+xx] = *(cc);
  953. //     fb[(yy)*f_w+(xx)]=*(cc);
  954. }
  955.  
  956. void DrawWuLine(int X0, int Y0, int X1, int Y1, byte *BaseColor,
  957.     int NumLevels, unsigned short IntensityBits)
  958. {
  959.    unsigned short IntensityShift, ErrorAdj, ErrorAcc;
  960.    unsigned short ErrorAccTemp, Weighting, WeightingComplementMask;
  961.    short DeltaX, DeltaY, Temp, XDir;
  962.  
  963.    /* Make sure the line runs top to bottom */
  964.    if (Y0 > Y1) {
  965.       Temp = Y0; Y0 = Y1; Y1 = Temp;
  966.       Temp = X0; X0 = X1; X1 = Temp;
  967.    }
  968.    /* Draw the initial pixel, which is always exactly intersected by
  969.       the line and so needs no weighting */
  970.    PUTDOT(X0, Y0, &BaseColor[0], NULL);
  971.  
  972.    if ((DeltaX = X1 - X0) >= 0) {
  973.       XDir = 1;
  974.    } else {
  975.       XDir = -1;
  976.       DeltaX = -DeltaX; /* make DeltaX positive */
  977.    }
  978.    /* Special-case horizontal, vertical, and diagonal lines, which
  979.       require no weighting because they go right through the center of
  980.       every pixel */
  981.    if ((DeltaY = Y1 - Y0) == 0) {
  982.       /* Horizontal line */
  983.       while (DeltaX-- != 0) {
  984.          X0 += XDir;
  985.          PUTDOT(X0, Y0, &BaseColor[0], NULL);
  986.       }
  987.       return;
  988.    }
  989.    if (DeltaX == 0) {
  990.       /* Vertical line */
  991.       do {
  992.          Y0++;
  993.          PUTDOT(X0, Y0, &BaseColor[0], NULL);
  994.       } while (--DeltaY != 0);
  995.       return;
  996.    }
  997.     //diagonal line.
  998.     if (DeltaX == DeltaY) {
  999.       do {
  1000.          X0 += XDir;
  1001.          Y0++;
  1002.          PUTDOT(X0, Y0, &BaseColor[0], NULL);
  1003.       } while (--DeltaY != 0);
  1004.       return;
  1005.    }
  1006.    /* Line is not horizontal, diagonal, or vertical */
  1007.    ErrorAcc = 0;  /* initialize the line error accumulator to 0 */
  1008.    /* # of bits by which to shift ErrorAcc to get intensity level */
  1009.    IntensityShift = 16 - IntensityBits;
  1010.    /* Mask used to flip all bits in an intensity weighting, producing the
  1011.       result (1 - intensity weighting) */
  1012.    WeightingComplementMask = NumLevels - 1;
  1013.    /* Is this an X-major or Y-major line? */
  1014.    if (DeltaY > DeltaX) {
  1015.       /* Y-major line; calculate 16-bit fixed-point fractional part of a
  1016.          pixel that X advances each time Y advances 1 pixel, truncating the
  1017.          result so that we won't overrun the endpoint along the X axis */
  1018.       ErrorAdj = ((unsigned long) DeltaX << 16) / (unsigned long) DeltaY;
  1019.       /* Draw all pixels other than the first and last */
  1020.       while (--DeltaY) {
  1021.          ErrorAccTemp = ErrorAcc;   /* remember currrent accumulated error */
  1022.          ErrorAcc += ErrorAdj;      /* calculate error for next pixel */
  1023.          if (ErrorAcc <= ErrorAccTemp) {
  1024.             /* The error accumulator turned over, so advance the X coord */
  1025.             X0 += XDir;
  1026.          }
  1027.          Y0++; /* Y-major, so always advance Y */
  1028.          /* The IntensityBits most significant bits of ErrorAcc give us the
  1029.             intensity weighting for this pixel, and the complement of the
  1030.             weighting for the paired pixel */
  1031.          Weighting = ErrorAcc >> IntensityShift;
  1032.             PUTDOT(X0, Y0, &BaseColor[Weighting], &BaseColor[7]);
  1033.          PUTDOT(X0 + XDir, Y0,
  1034.                &BaseColor[(Weighting ^ WeightingComplementMask)], &BaseColor[7]);
  1035.       }
  1036.       /* Draw the final pixel, which is always exactly intersected by the line
  1037.          and so needs no weighting */
  1038.       PUTDOT(X1, Y1, &BaseColor[0], NULL);
  1039.       return;
  1040.    }
  1041.    /* It's an X-major line; calculate 16-bit fixed-point fractional part of a
  1042.       pixel that Y advances each time X advances 1 pixel, truncating the
  1043.       result to avoid overrunning the endpoint along the X axis */
  1044.    ErrorAdj = ((unsigned long) DeltaY << 16) / (unsigned long) DeltaX;
  1045.    /* Draw all pixels other than the first and last */
  1046.    while (--DeltaX) {
  1047.       ErrorAccTemp = ErrorAcc;   /* remember currrent accumulated error */
  1048.       ErrorAcc += ErrorAdj;      /* calculate error for next pixel */
  1049.       if (ErrorAcc <= ErrorAccTemp) {
  1050.          /* The error accumulator turned over, so advance the Y coord */
  1051.          Y0++;
  1052.       }
  1053.       X0 += XDir; /* X-major, so always advance X */
  1054.       /* The IntensityBits most significant bits of ErrorAcc give us the
  1055.          intensity weighting for this pixel, and the complement of the
  1056.          weighting for the paired pixel */
  1057.       Weighting = ErrorAcc >> IntensityShift;
  1058.       PUTDOT(X0, Y0, &BaseColor[Weighting], &BaseColor[7]);
  1059.       PUTDOT(X0, Y0 + 1,
  1060.               &BaseColor[(Weighting ^ WeightingComplementMask)], &BaseColor[7]);
  1061.  
  1062.    }
  1063.    /* Draw the final pixel, which is always exactly intersected by the line
  1064.       and so needs no weighting */
  1065.    PUTDOT(X1, Y1, &BaseColor[0], NULL);
  1066. }
  1067.  
  1068. void AM_drawMline(mline_t *ml, int color)
  1069. {
  1070.   static fline_t fl;
  1071.  
  1072.   if (AM_clipMline(ml, &fl))
  1073.     AM_drawFline(&fl, color); // draws it on frame buffer using fb coords
  1074.  
  1075. }
  1076.  
  1077. void AM_drawGrid(int color)
  1078. {
  1079.   fixed_t x, y;
  1080.   fixed_t start, end;
  1081.   mline_t ml;
  1082.  
  1083.   // Figure out start of vertical gridlines
  1084.   start = m_x;
  1085.   if ((start-bmaporgx)%(MAPBLOCKUNITS<<FRACBITS))
  1086.     start += (MAPBLOCKUNITS<<FRACBITS)
  1087.       - ((start-bmaporgx)%(MAPBLOCKUNITS<<FRACBITS));
  1088.   end = m_x + m_w;
  1089.  
  1090.   // draw vertical gridlines
  1091.   ml.a.y = m_y;
  1092.   ml.b.y = m_y+m_h;
  1093.   for (x=start; x<end; x+=(MAPBLOCKUNITS<<FRACBITS))
  1094.   {
  1095.     ml.a.x = x;
  1096.     ml.b.x = x;
  1097.     AM_drawMline(&ml, color);
  1098.   }
  1099.  
  1100.   // Figure out start of horizontal gridlines
  1101.   start = m_y;
  1102.   if ((start-bmaporgy)%(MAPBLOCKUNITS<<FRACBITS))
  1103.     start += (MAPBLOCKUNITS<<FRACBITS)
  1104.       - ((start-bmaporgy)%(MAPBLOCKUNITS<<FRACBITS));
  1105.   end = m_y + m_h;
  1106.  
  1107.   // draw horizontal gridlines
  1108.   ml.a.x = m_x;
  1109.   ml.b.x = m_x + m_w;
  1110.   for (y=start; y<end; y+=(MAPBLOCKUNITS<<FRACBITS))
  1111.   {
  1112.     ml.a.y = y;
  1113.     ml.b.y = y;
  1114.     AM_drawMline(&ml, color);
  1115.   }
  1116. }
  1117.  
  1118. void AM_drawWalls(void)
  1119. {
  1120.   int i;
  1121.   static mline_t l;
  1122.  
  1123.   for (i=0;i<numlines;i++)
  1124.   {
  1125.     l.a.x = lines[i].v1->x;
  1126.     l.a.y = lines[i].v1->y;
  1127.     l.b.x = lines[i].v2->x;
  1128.     l.b.y = lines[i].v2->y;
  1129.     if (cheating || (lines[i].flags & ML_MAPPED))
  1130.     {
  1131.       if ((lines[i].flags & LINE_NEVERSEE) && !cheating)
  1132.             continue;
  1133.       if (!lines[i].backsector)
  1134.       {
  1135.         AM_drawMline(&l, WALLCOLORS+lightlev);
  1136.       } else {
  1137.     if (lines[i].special == 39)
  1138.     { // teleporters
  1139.           AM_drawMline(&l, WALLCOLORS+WALLRANGE/2);
  1140.     } else if (lines[i].flags & ML_SECRET) // secret door
  1141.     {
  1142.       if (cheating) AM_drawMline(&l, 0);
  1143.       else AM_drawMline(&l, WALLCOLORS+lightlev);
  1144.     }
  1145.     else if(lines[i].special > 25 && lines[i].special < 35)
  1146.     {
  1147.         switch(lines[i].special)
  1148.         {
  1149.             case 26:
  1150.             case 32:
  1151.                 AM_drawMline(&l, BLUEKEY);
  1152.                 break;
  1153.             case 27:
  1154.             case 34:
  1155.                 AM_drawMline(&l, YELLOWKEY);
  1156.                 break;
  1157.             case 28:
  1158.             case 33:
  1159.                 AM_drawMline(&l, GREENKEY);
  1160.                 break;
  1161.             default:
  1162.                 break;
  1163.         }
  1164.     }
  1165.     else if (lines[i].backsector->floorheight
  1166.            != lines[i].frontsector->floorheight) {
  1167.       AM_drawMline(&l, FDWALLCOLORS + lightlev); // floor level change
  1168.     } else if (lines[i].backsector->ceilingheight
  1169.            != lines[i].frontsector->ceilingheight) {
  1170.       AM_drawMline(&l, CDWALLCOLORS+lightlev); // ceiling level change
  1171.     } else if (cheating) {
  1172.       AM_drawMline(&l, TSWALLCOLORS+lightlev);
  1173.     }
  1174.       }
  1175.     } else if (plr->powers[pw_allmap])
  1176.     {
  1177.       if (!(lines[i].flags & LINE_NEVERSEE)) AM_drawMline(&l, GRAYS+3);
  1178.     }
  1179.   }
  1180.  
  1181. }
  1182.  
  1183. void AM_rotate(fixed_t *x, fixed_t *y, angle_t a)
  1184. {
  1185.   fixed_t tmpx;
  1186.  
  1187.   tmpx = FixedMul(*x,finecosine[a>>ANGLETOFINESHIFT])
  1188.        - FixedMul(*y,finesine[a>>ANGLETOFINESHIFT]);
  1189.   *y   = FixedMul(*x,finesine[a>>ANGLETOFINESHIFT])
  1190.        + FixedMul(*y,finecosine[a>>ANGLETOFINESHIFT]);
  1191.   *x = tmpx;
  1192. }
  1193.  
  1194. void AM_drawLineCharacter(mline_t *lineguy, int lineguylines, fixed_t scale,
  1195.   angle_t angle, int color, fixed_t x, fixed_t y)
  1196. {
  1197.   int i;
  1198.   mline_t l;
  1199.  
  1200.   for (i=0;i<lineguylines;i++)
  1201.   {
  1202.     l.a.x = lineguy[i].a.x;
  1203.     l.a.y = lineguy[i].a.y;
  1204.     if (scale)
  1205.     {
  1206.       l.a.x = FixedMul(scale, l.a.x);
  1207.       l.a.y = FixedMul(scale, l.a.y);
  1208.     }
  1209.     if (angle) AM_rotate(&l.a.x, &l.a.y, angle);
  1210.     l.a.x += x;
  1211.     l.a.y += y;
  1212.  
  1213.     l.b.x = lineguy[i].b.x;
  1214.     l.b.y = lineguy[i].b.y;
  1215.     if (scale)
  1216.     {
  1217.       l.b.x = FixedMul(scale, l.b.x);
  1218.       l.b.y = FixedMul(scale, l.b.y);
  1219.     }
  1220.     if (angle) AM_rotate(&l.b.x, &l.b.y, angle);
  1221.     l.b.x += x;
  1222.     l.b.y += y;
  1223.  
  1224.     AM_drawMline(&l, color);
  1225.   }
  1226.  
  1227. }
  1228.  
  1229. void AM_drawPlayers(void)
  1230. {
  1231.  
  1232.   int i;
  1233.   player_t *p;
  1234.   static int their_colors[] = { GREENKEY, YELLOWKEY, BLOODRED, BLUEKEY };
  1235.   int their_color = -1;
  1236.   int color;
  1237.  
  1238.   if (!netgame)
  1239.   {
  1240.     /*
  1241.     if (cheating) AM_drawLineCharacter(cheat_player_arrow, NUMCHEATPLYRLINES, 0,
  1242.       plr->mo->angle, WHITE, plr->mo->x, plr->mo->y);
  1243.      */ //cheat key player pointer is the same as non-cheat pointer..
  1244.  
  1245.         AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 0, plr->mo->angle,
  1246.       WHITE, plr->mo->x, plr->mo->y);
  1247.     return;
  1248.   }
  1249.  
  1250.   for (i=0;i<MAXPLAYERS;i++)
  1251.   {
  1252.     their_color++;
  1253.     p = &players[i];
  1254.     if(deathmatch && !singledemo && p != plr)
  1255.     {
  1256.     continue;
  1257.     }
  1258.     if (!playeringame[i]) continue;
  1259.     if (p->powers[pw_invisibility]) color = 102; // *close* to the automap color
  1260.     else color = their_colors[their_color];
  1261.     AM_drawLineCharacter(player_arrow, NUMPLYRLINES, 0, p->mo->angle,
  1262.       color, p->mo->x, p->mo->y);
  1263.   }
  1264. }
  1265.  
  1266. void AM_drawThings(int colors, int colorrange)
  1267. {
  1268.   int i;
  1269.   mobj_t *t;
  1270.  
  1271.   for (i=0;i<numsectors;i++)
  1272.   {
  1273.     t = sectors[i].thinglist;
  1274.     while (t)
  1275.     {
  1276.       AM_drawLineCharacter(thintriangle_guy, NUMTHINTRIANGLEGUYLINES,
  1277.     16<<FRACBITS, t->angle, colors+lightlev, t->x, t->y);
  1278.       t = t->snext;
  1279.     }
  1280.   }
  1281. }
  1282.  
  1283. /*
  1284. void AM_drawMarks(void)
  1285. {
  1286.   int i, fx, fy, w, h;
  1287.  
  1288.   for (i=0;i<AM_NUMMARKPOINTS;i++)
  1289.   {
  1290.     if (markpoints[i].x != -1)
  1291.     {
  1292.       w = SHORT(marknums[i]->width);
  1293.       h = SHORT(marknums[i]->height);
  1294.       fx = CXMTOF(markpoints[i].x);
  1295.       fy = CYMTOF(markpoints[i].y);
  1296.       if (fx >= f_x && fx <= f_w - w && fy >= f_y && fy <= f_h - h)
  1297.               V_DrawPatch(fx, fy, marknums[i]);
  1298.     }
  1299.   }
  1300. }
  1301. */
  1302.  
  1303. void AM_drawkeys(void)
  1304. {
  1305.     if(KeyPoints[0].x != 0 || KeyPoints[0].y != 0)
  1306.     {
  1307.         AM_drawLineCharacter(keysquare, NUMKEYSQUARELINES, 0, 0, YELLOWKEY,
  1308.             KeyPoints[0].x, KeyPoints[0].y);
  1309.     }
  1310.     if(KeyPoints[1].x != 0 || KeyPoints[1].y != 0)
  1311.     {
  1312.         AM_drawLineCharacter(keysquare, NUMKEYSQUARELINES, 0, 0, GREENKEY,
  1313.             KeyPoints[1].x, KeyPoints[1].y);
  1314.     }
  1315.     if(KeyPoints[2].x != 0 || KeyPoints[2].y != 0)
  1316.     {
  1317.         AM_drawLineCharacter(keysquare, NUMKEYSQUARELINES, 0, 0, BLUEKEY,
  1318.             KeyPoints[2].x, KeyPoints[2].y);
  1319.     }
  1320. }
  1321.  
  1322. void AM_drawCrosshair(int color)
  1323. {
  1324.   fb[(f_w*(f_h+1))/2] = color; // single point for now
  1325. }
  1326.  
  1327. void AM_Drawer(void)
  1328. {
  1329.     int highestEpisode;
  1330.  
  1331.     if (!automapactive) return;
  1332.  
  1333.   UpdateState |= I_FULLSCRN;
  1334.   AM_clearFB(BACKGROUND);
  1335.   if (grid) AM_drawGrid(GRIDCOLORS);
  1336.   AM_drawWalls();
  1337.   AM_drawPlayers();
  1338.   if (cheating==2) AM_drawThings(THINGCOLORS, THINGRANGE);
  1339. //  AM_drawCrosshair(XHAIRCOLORS);
  1340.  
  1341. //  AM_drawMarks();
  1342.     if(gameskill == sk_baby)
  1343.     {
  1344.         AM_drawkeys();
  1345.     }
  1346.     if((gameepisode < (ExtendedWAD ? 6 : 4)) && gamemap < 10)
  1347.     {
  1348.         MN_DrTextA(LevelNames[(gameepisode-1)*9+gamemap-1], 20, 145);
  1349.     }
  1350. //  I_Update();
  1351. //  V_MarkRect(f_x, f_y, f_w, f_h);
  1352. }
  1353.